using UnityEngine; 
using System.Collections; 
using System.Xml; 
using System.Xml.Serialization; 
using System.IO; 
using System.Text; 
using XMLData.Map;
using XMLData.UnityObject;
using XMLReaderWriter;


namespace XMLData
{	
	namespace UnityObject
	{
		public class XMLVector3
		{
			public XMLVector3(){}
			public float x;
			public float y;
			public float z;
			
			public void SetValue(Vector3 vec3)
			{
				x = vec3.x;
				y = vec3.y;
				z = vec3.z;
			}
		}
		public class XMLMaterial
		{
			public Asset mainTexture;
			public XMLVector2 offSet;
			public XMLVector2 scale;
		}
		public class XMLVector2
		{
			public XMLVector2(){}
			public float x;
			public float y;
			
			public void SetValue(Vector2 vec2)
			{
				x = vec2.x;
				y = vec2.y;
			}
		}
		public class XMLTransform
		{
			public XMLTransform(){}
			public XMLVector3 position;
			public XMLVector3 rotation;
			public XMLVector3 scale;
			
			public void SetValue(Transform transform)
			{
				position.SetValue(transform.position);
				rotation.SetValue(transform.rotation.eulerAngles);
				scale.SetValue(transform.localScale);
			}
		}
		
		public class XMLBoxCollider
		{
			public XMLBoxCollider(){}
			public XMLVector3 center;
			public XMLVector3 size;
			public void SetValue(BoxCollider boxCollider)
			{
				center.SetValue(boxCollider.center);
				size.SetValue(boxCollider.size);
			}
		}
		
		public class XMLGameObject
		{
			public XMLGameObject(){}
			public XMLTransform transform;
			public XMLBoxCollider boxCollider;
		}
		
	}
	
	namespace Map
	{
		public class MapLevel
		{
			string _FileLocation,_FileName;
		}
		
		public class ICell
		{
			public ICell() {}
			
			//Is visible
			public bool iSee;
			
			public float x;
			public float y;
			public float z;
			//Name
			public string n;
			
			//Grid Pos
			public int gX;
			public int gY;
		}
		
		public class PlatformInfo
		{
			public float fromPos;
			public float toPos;
			public bool  isX;
		}
		
		[System.Serializable]
		public class TileObject
		{
			public TileObject(){}
			public int objectType;
			public int ID;
			public bool isBothWorlds;
			public bool isLinked;
			public int linkedID;
			public int layerMask;
			
			public float chomperCounter;
			public int ladderSize;
			public string tutName;
			public PlatformInfo platformInfo;
			public XMLVector3 position;
		}
			
		public class LayerManagerInfo
		{
			public LayerManagerInfo(){}
			public Layer2DInfo[] layers;
			public int layerMask;
			public float initialZPosition;
		}
		
		public class Layer2DInfo
		{
			public Layer2DInfo(){}
			public Plane2DInfo[] plane2DList;
			public int layerIndex;
			public string name;
			public int layerMask;
			public float zPosition;
		}
		
		public class Plane2DInfo
		{
			public Plane2DInfo(){}
			public string planeName;
			public int Layer2DIndex;
			public XMLMaterial planeMaterial;
			public XMLVector2 scale;
			public XMLVector2 position;
		}
		
		public class Asset
		{
			public Asset(){}
			public string name;
			public int assetType;
		}
		
		public class XMLCluster
		{
			//CellInfo == TileUnit
			public TilePos[] tileUnit;
			public int gridPosY;
			public int layerMask;
		}
			
		public class TilePos
		{
			public TilePos(){}
			public int gridPosX;
			public int gridPosY;
		}
		
		public class MapInfo
		{
			public XMLCluster[] clusterList;
			
			[XmlArray("W1")]
			public ICell[] world1;
			public string bg1;
			public string nextMap;
			public TileObject[] tileObj1;
			
			[XmlArray("W2")]
			public ICell[] world2;
			public TileObject[] tileObj2;
			
			[XmlElement("LenthX")]
			public int lengthX;
			
			[XmlElement("LenthY")]
			public int lengthY;
		}
	}
}

namespace XMLReaderWriter
{
	abstract class BaseReaderWriter
	{
	    protected string _FileLocation,_FileName;
	    bool isFileExisting = false;
		
	   	public BaseReaderWriter(string fileName)
		{
			_FileLocation = Application.dataPath;
			_FileName = fileName;
		}
	   protected string UTF8ByteArrayToString(byte[] characters) 
	   {      
	      UTF8Encoding encoding = new UTF8Encoding(); 
	      string constructedString = encoding.GetString(characters); 
	      return (constructedString); 
	   } 
	 
	   protected byte[] StringToUTF8ByteArray(string pXmlString) 
	   { 
	      UTF8Encoding encoding = new UTF8Encoding(); 
	      byte[] byteArray = encoding.GetBytes(pXmlString); 
	      return byteArray; 
	   }
	   
		abstract protected string SerializeObject(object pObject);
		abstract protected object DeserializeObject(string pXmlizedString);
		
		public bool CheckFileExistence()
		{
			return isFileExisting;
		}
		public void CreateXML(object pObject)
		{
				
			string _data = SerializeObject(pObject);
			StreamWriter writer; 
		    FileInfo t = new FileInfo(_FileLocation+"/"+ _FileName); 
		    if(!t.Exists) 
		    { 
		    	writer = t.CreateText();
		    } 
		    else 
		    { 
		    	t.Delete(); 
		        writer = t.CreateText(); 
		    }
			
			isFileExisting = t.Exists;
			
		    writer.Write(_data); 
		    writer.Close();
		    Debug.Log("File "+ _FileName +" written."); 
		}
		
		public void Delete()
		{
			try
			{
			    // A.
			    // Try to delete the file.
			    File.Delete(_FileLocation+"/"+ _FileName);
			}
			catch (IOException)
			{
			    
			}
		}
				
		public object LoadXML()
		{
			if(!File.Exists(_FileLocation+"/"+ _FileName))
			{
				isFileExisting = false;
				return null;
			}
			StreamReader r = File.OpenText(_FileLocation+"/"+ _FileName); 
		    string _info = r.ReadToEnd(); 
		    r.Close();
			if(_info.ToString() != "")
			{
				isFileExisting = true;
				object _tmp = DeserializeObject(_info);
		    	Debug.Log("File "+ _FileName +" read."); 
				return _tmp;
			}
			else
			{
				isFileExisting = false;
				Debug.Log("File "+ _FileName +" is not existing."); 
				return null;
			}
		}
		
		public string extractString()
		{
			if(!File.Exists(_FileLocation+"/"+ _FileName))
			{
				isFileExisting = false;
				return null;
			}
			StreamReader r = File.OpenText(_FileLocation+"/"+ _FileName); 
		    return r.ReadToEnd(); 
		}
		
		public void saveMap(string Data)
		{
			StreamWriter writer; 
		    FileInfo t = new FileInfo(_FileLocation + "/" + _FileName); 
		    if(!t.Exists) 
		    { 
		    	writer = t.CreateText();
		    } 
		    else 
		    { 
		    	t.Delete(); 
		        writer = t.CreateText(); 
		    }
			
			isFileExisting = t.Exists;
			
		    writer.Write(Data); 
		    writer.Close();
		}
	}
	
	class MapInfoXML:BaseReaderWriter
	{
		public MapInfoXML(string fileName)
			:base(fileName)
		{
			string desireLocation = Application.dataPath + "/Maps";
			if(!Directory.Exists(desireLocation))
			{
				Directory.CreateDirectory(desireLocation);
			}
			this._FileLocation = desireLocation;
		}
		
		
		protected override object DeserializeObject (string pXmlizedString)
		{
			XmlSerializer xs = new XmlSerializer(typeof(MapInfo)); 
	        MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString)); 
	        //XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
	        return xs.Deserialize(memoryStream); 
		}
		
		protected override string SerializeObject (object pObject)
		{
			string XmlizedString = null; 
		    XmlSerializer xs = new XmlSerializer(typeof(MapInfo)); 
			MemoryStream memoryStream = new MemoryStream(); 
		    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
		    xs.Serialize(xmlTextWriter, pObject); 
		    memoryStream = (MemoryStream)xmlTextWriter.BaseStream; 
		    XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray()); 
		    return XmlizedString; 
		}
	}
	
	class StrArrayXML:BaseReaderWriter
	{
		public StrArrayXML(string fileName):
			base(fileName){}
		
		protected override object DeserializeObject (string pXmlizedString)
		{
			XmlSerializer xs = new XmlSerializer(typeof(string[])); 
	        MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString)); 
	        //XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
	        return xs.Deserialize(memoryStream); 
		}
		
		protected override string SerializeObject (object pObject)
		{
			string XmlizedString = null; 
		    XmlSerializer xs = new XmlSerializer(typeof(string[])); 
			MemoryStream memoryStream = new MemoryStream(); 
		    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
		    xs.Serialize(xmlTextWriter, pObject); 
		    memoryStream = (MemoryStream)xmlTextWriter.BaseStream; 
		    XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray()); 
		    return XmlizedString; 
		}
	}
}
